#include "pcrChartManager.h"

PCRChartManager::PCRChartManager(QWidget *parent){

    this->setParent(parent);

    _chartView = new QChartView(this);
    _chartView->setRenderHint(QPainter::RenderHint::Antialiasing);

    _layout = new QHBoxLayout(this);
    _layout->addWidget(_chartView);
    this->setLayout(_layout);

    _chart = "";

}

void PCRChartManager::init(PCRState *state){
    pState = state;
    this->addChart("chartRaw");
    this->addChart("chartRn");
    this->addChart("chartDeltaRn");
    this->addChart("chartLogRn");
    this->addChart("chartLogDeltaRn");
    this->addChart("chartNormRn");
    this->addChart("chartStandard");
    _chartMap["chartStandard"]->legend()->show();
    this->changeChart("chartRaw");

    _chartMap["chartRaw"]->axisX()->setTitleText("循环数(Cycles)");
    _chartMap["chartRn"]->axisX()->setTitleText("循环数(Cycles)");
    _chartMap["chartDeltaRn"]->axisX()->setTitleText("循环数(Cycles)");
    _chartMap["chartLogRn"]->axisX()->setTitleText("循环数(Cycles)");
    _chartMap["chartLogDeltaRn"]->axisX()->setTitleText("循环数(Cycles)");
    _chartMap["chartNormRn"]->axisX()->setTitleText("循环数(Cycles)");
    _chartMap["chartStandard"]->axisX()->setTitleText("浓度");

    ((QValueAxis*)_chartMap["chartNormRn"]->axisY())->setLabelFormat("%.2f");
    ((QValueAxis*)_chartMap["chartLogRn"]->axisY())->setLabelFormat("%.2f");
    ((QValueAxis*)_chartMap["chartLogDeltaRn"]->axisY())->setLabelFormat("%.2f");


    _chartMap["chartRaw"]->axisY()->setTitleText("荧光强度(Ru)");
    _chartMap["chartRn"]->axisY()->setTitleText("荧光强度(Rn)");
    _chartMap["chartDeltaRn"]->axisY()->setTitleText("荧光强度(ΔRn)");
    _chartMap["chartLogRn"]->axisY()->setTitleText("荧光强度(Rn)");
    _chartMap["chartLogDeltaRn"]->axisY()->setTitleText("荧光强度(ΔRn)");
    _chartMap["chartNormRn"]->axisY()->setTitleText("荧光强度(ΔRn)");
    _chartMap["chartStandard"]->axisY()->setTitleText("CT值");

    updateStandardLegend();

}


void PCRChartManager::on_pageChanged(){

    switch (pState->currentPage) {
    case PCRState::RAW:
        this->changeChart("chartRaw");
        break;
    case PCRState::RN:
        this->changeChart("chartRn");
        break;
    case PCRState::LOG_RN:
        this->changeChart("chartLogRn");
        break;
    case PCRState::LOG_DELTA_RN:
        this->changeChart("chartLogDeltaRn");
        break;
    case PCRState::DELTA_RN:
        this->changeChart("chartDeltaRn");
        break;
    case PCRState::NORM_RN:
        this->changeChart("chartNormRn");
        break;
    case PCRState::STANDARD:
        this->changeChart("chartStandard");
        break;
    case PCRState::GUIDE_DATA:
        break;
    case PCRState::GUIDE_PLAN:
        break;
    }

    this->updateShow();
    this->updateStandardLegend();

}

void PCRChartManager::on_filterResultChanged(){

    this->updateShow();
    this->updateStandardLegend();
}

void PCRChartManager::on_boldResultChanged(){

    this->updateShow();
    this->updateStandardLegend();
}

void PCRChartManager::on_thrChanged(){

    this->updateThreshold();
    this->updateShow();
    this->updateStandardLegend();
}

void PCRChartManager::on_standardChanged(){
    // 标准曲线
    for(auto iter = pState->standardLine.begin(); iter != pState->standardLine.end(); iter ++){
        if(iter.key() == pState->modelIR) continue;
        this->addCurve(iter.key() + "_STANDARD", "chartStandard", createStandardCurve(iter.value()[0], iter.value()[1]));
    }
    for(auto iter = pState->modelList.begin(); iter != pState->modelList.end(); iter ++){
        if(iter.key().channel() == pState->modelIR) continue;
        QVector<QPointF> point; point.append(pState->standardPoint[iter.key()]);
        this->addCurve(iter.key(), "chartStandard", point, "scatter");

    }

    this->updateThreshold();
    this->updateStandardLegend();

}

int PCRChartManager::addChart(QString chartName){
    if(_chartMap.contains(chartName)){
        return -1;
    }
    _chartMap.insert(chartName, new PCRChartItem(this));
    return 0;
}

int PCRChartManager::addCurve(QString name, QString chartName, const QVector<QPointF> &pointList, QString type){
    if(!_chartMap.contains(chartName)){
        return -1;
    }
   _chartMap[chartName]->appendCurve(name, pointList, type);
   return 0;
}



int PCRChartManager::changeChart(QString name){
    if(!_chartMap.contains(name)){
        return -1;
    }
    _chart = name;
    _chartView->setChart(_chartMap[name]);
    return 0;
}


QString PCRChartManager::getChartName(){
    return _chart;
}


void PCRChartManager::updateThreshold(){

    foreach(ChannelName channel, pState->channelList){
        addCurve(channel+"_THR", "chartDeltaRn",    createThrCurve(pState->thrList[channel]),       "spline");
        addCurve(channel+"_THR", "chartLogDeltaRn", createThrCurve(pState->thrList_log[channel]),   "spline");
        addCurve(channel+"_THR", "chartNormRn",     createThrCurve(pState->thrList_diff[channel]),  "spline");
        addCurve(channel+"_THR", "chartRn",         createThrCurve(pState->thrList_Rn[channel]),    "spline");
        addCurve(channel+"_THR", "chartLogRn",      createThrCurve(pState->thrList_logRn[channel]), "spline");
    }

}


void PCRChartManager::updateShow(){


    PCRChartItem* chart = _chartMap[_chart];

    // 曲线状态更新
    chart->changeCurveState_reg("", PCRChartItem::HIDE);
    chart->changeCurveState(pState->filterResult, PCRChartItem::NORM);
    chart->changeCurveState(pState->boldResult, PCRChartItem::BOLD);
    chart->changeCurveState_reg("_STANDARD", PCRChartItem::NORM);

    // 阈值线状态更新
    if(pState->showThr){
        foreach(ChannelName channel, pState->channelList){
            if(channel != pState->modelIR)
                chart->changeCurveState(channel+"_THR", PCRChartItem::NORM);
        }
        for(auto iter = pState->channelList_filter.begin(); iter != pState->channelList_filter.end(); iter ++){

        }
    }else{
        chart->changeCurveState("THR", PCRChartItem::HIDE);
    }

    // 执行更新
    chart->updateCurve();

    if(_chart == "chartStandard"){
        chart->updateRange(-5, 5, 1, pState->cycleNum);
    }else{
        chart->updateRange();
    }

}


void PCRChartManager::updateStandardLegend(){

    QVector<QPointF> pl;
    pl.append(QPointF(0, QRandomGenerator::global()->bounded(10,20)));
    _chartMap["chartStandard"]->appendCurve("a", pl, "scatter");

    QLegend *legend = _chartMap["chartStandard"]->legend();
    legend->detachFromChart();
    legend->setAlignment(Qt::AlignBottom);
    _chartMap["chartStandard"]->setMargins(QMargins(30, 20, 30, 170));

    legend->setGeometry(QRectF(40,_chartView->height()-200,500,160));


    if(legend){
        QList<QLegendMarker*> markers = legend->markers();
        if (!markers.isEmpty()) {
            for(int i = 0; i < markers.size(); i ++){
                markers[i]->setVisible(true);
                if(markers[i]->label().contains("FAM") && (markers[i]->label().contains("STANDARD") || markers[i]->label().size()> 10)){
                    double k = pState->standardLine["FAM"][0];
                    double b = pState->standardLine["FAM"][1];
                    markers[i]->setLabel("FAM  K=" + QString::number(k, 'f', 2) + "\ty-int=" + QString::number(b, 'f', 2) + "\tE=" + QString::number((pow(10, -1.0/k)-1)*100, 'f', 2)+"%" + "\tR^2=0.00");
                }else if(markers[i]->label().contains("VIC") && (markers[i]->label().contains("STANDARD") || markers[i]->label().size()> 10)){
                    double k = pState->standardLine["VIC"][0];
                    double b = pState->standardLine["VIC"][1];
                    markers[i]->setLabel("VIC  K=" + QString::number(k, 'f', 2) + "\ty-int=" + QString::number(b, 'f', 2) + "\tE=" + QString::number((pow(10, -1.0/k)-1)*100, 'f', 2)+"%" + "\tR^2=0.00");
                }else if(markers[i]->label().contains("ROX") && (markers[i]->label().contains("STANDARD") || markers[i]->label().size()> 10)){
                    double k = pState->standardLine["ROX"][0];
                    double b = pState->standardLine["ROX"][1];
                    markers[i]->setLabel("ROX  K=" + QString::number(k, 'f', 2) + "\ty-int=" + QString::number(b, 'f', 2) + "\tE=" + QString::number((pow(10, -1.0/k)-1)*100, 'f', 2)+"%" + "\tR^2=0.00");
                }else if(markers[i]->label().contains("CY5") && (markers[i]->label().contains("STANDARD") || markers[i]->label().size()> 10)){
                    double k = pState->standardLine["CY5"][0];
                    double b = pState->standardLine["CY5"][1];
                    markers[i]->setLabel("CY5  K=" + QString::number(k, 'f', 2) + "\ty-int=" + QString::number(b, 'f', 2) + "\tE=" + QString::number((pow(10, -1.0/k)-1)*100, 'f', 2)+"%" + "\tR^2=0.00");
                }else{
                    markers[i]->setVisible(false);
                }
            }
        }else{
            qDebug("markers为空");
        }
    }else{
        qDebug("更新失败");
    }
}


QVector<QPointF> PCRChartManager::createThrCurve(double value){

    QVector<QPointF> line;
    if(pState == nullptr){
        return line;
    }
    line.append(QPointF(0, value));
    line.append(QPointF(pState->cycleNum, value));

    return line;
}


QVector<QPointF> PCRChartManager::createStandardCurve(double k, double b){
    QVector<QPointF> line;
    if(pState == nullptr){
        return line;
    }
    double start = -5;
    double end = 5;
    // [TODO] 动态变更标准曲线的绘制范围
    line.append(QPointF(start, k*start+b));
    line.append(QPointF(end, k*end+b));
    return line;

}

void PCRChartManager::on_modelChanged(){

    // 荧光曲线
    for(auto iter = pState->modelList.begin(); iter != pState->modelList.end(); iter ++){
        QPCRModel::Model* model = iter.value();
        this->addCurve(iter.key(), "chartRaw", pState->rawData_filter[iter.key()]);
        this->addCurve(iter.key(), "chartRn", model->getFittedData());
        this->addCurve(iter.key(), "chartDeltaRn", model->getFittedData_delta());
        this->addCurve(iter.key(), "chartLogRn", model->getFittedData_log());
        this->addCurve(iter.key(), "chartLogDeltaRn", model->getFittedData_log_delta());
        //this->addCurve(iter.key(), "chartNormRn", model->getFittedData_norm());
        this->addCurve(iter.key(), "chartNormRn", model->getFittedDate_diff(pState->rangeIR[iter.key().posi()]));

        // 标准曲线上的点
        if(iter.key().channel() == pState->modelIR) continue;
        QVector<QPointF> point; point.append(pState->standardPoint[iter.key()]);
        this->addCurve(iter.key(), "chartStandard", point, "scatter");
    }
    // 标准曲线
    for(auto iter = pState->standardLine.begin(); iter != pState->standardLine.end(); iter ++){
        if(iter.key() == pState->modelIR) continue;
        this->addCurve(iter.key() + "_STANDARD", "chartStandard", createStandardCurve(iter.value()[0], iter.value()[1]));
    }

    this->updateThreshold();
    this->updateShow();
    this->updateStandardLegend();

}

void PCRChartManager::resizeEvent(QResizeEvent *event){     // 更新标准曲线的legend位置


    if(! _chartMap.contains("chartStandard")){
        QWidget::resizeEvent(event);
        return;
    }
    this->updateStandardLegend();
    QWidget::resizeEvent(event);


}
